import { _decorator, Component, ImageAsset, Node, size, Sprite, SpriteFrame, Texture2D, v4, Vec4 } from 'cc';
const { ccclass, property, executeInEditMode, requireComponent } = _decorator;

@ccclass('PixelSprite')
@requireComponent(Sprite)
// @executeInEditMode
export class PixelSprite extends Component {

    img: ImageAsset = null;
    buffer: Uint8Array = null;
    sprite: Sprite = null;
    texture: Texture2D = null;
    isDirty = true;
    pixelArr: number[] = [];
    textureSize = size(0, 0);

    protected onEnable(): void {
        //test
        // this.setData(5, 5, TestData);
    }

    protected lateUpdate(dt: number): void {
        if (this.isDirty && this.texture) {
            this.isDirty = false;
            // 更新
            this.texture.uploadData(this.buffer);
        }
    }
    // 设置数据
    public setData(w: number, h: number, data?: number[]): SpriteFrame {
        this.textureSize = size(w, h);

        const _size = size(w, h);
        this.pixelArr = data || this.createPixelArr(w, h);
        if (this.pixelArr.length != _size.width * _size.height) {
            console.error('data.length != _size.width * _size.height');
            return null;
        }

        const len = _size.width * _size.height * 4;
        this.buffer = new Uint8Array(len);

        let pixelIdx = 0;
        for (let i = 0; i < len; i += 4) {
            // x: 控制是否展示
            this.buffer[i] = 255 * this.pixelArr[pixelIdx++];
            this.buffer[i + 1] = 255;
            this.buffer[i + 2] = 255;
            this.buffer[i + 3] = 255;
        }

        const sf = this.createSpriteFrame(_size.width, _size.height, this.buffer);
        this.sprite = this.node.getComponent(Sprite);
        this.sprite.spriteFrame = sf;
        this.sprite.sizeMode = Sprite.SizeMode.CUSTOM;
        // 设置材质参数
        if (this.sprite.customMaterial) {
            this.sprite.customMaterial.setProperty('pixelSize', v4(w, h, 0, 0));
        }

        return sf;
    }
    /**
     * 更新指定像素位置数据
     * @param x 
     * @param y 
     * @param val :xyzw对应rgba
     * @returns 
     */
    public updateData(x: number, y: number, val: Vec4) {
        if (this.pixelArr.length == 0) {
            console.error('pixelArr.length == 0');
            return false;
        }
        const idx = y * this.textureSize.width * 4 + x * 4;

        if (idx >= 0 && idx < this.buffer.length) {
            this.buffer[idx] = val.x * 255;
            this.buffer[idx + 1] = val.y * 255;
            this.buffer[idx + 2] = val.z * 255;
            this.buffer[idx + 3] = val.w * 255;
            this.isDirty = true;
            return true;
        }
        return false;
    }

    // 创建像素数组
    private createPixelArr(w: number, h: number, val = 1) {
        const arr = [];
        const len = w * h;
        for (let i = 0; i < len; i++) {
            arr.push(val);
        }
        return arr;
    }
    // 创建SpriteFrame
    private createSpriteFrame(width, height, buffer) {

        this.img = new ImageAsset();
        this.img.reset({
            _data: buffer,
            width: width,
            height: height,
            format: Texture2D.PixelFormat.RGBA8888,
            _compressed: false,
        });

        this.texture = new Texture2D();
        // 过滤模式
        this.texture.setFilters(Texture2D.Filter.NONE, Texture2D.Filter.NONE);
        // 拼接模式
        this.texture.setWrapMode(Texture2D.WrapMode.CLAMP_TO_EDGE, Texture2D.WrapMode.CLAMP_TO_EDGE);

        let sf = new SpriteFrame();
        this.texture.image = this.img;
        sf.texture = this.texture;
        sf.packable = false; // 默认不合批
        sf.flipUVY = false;   // 翻转图片
        sf.flipUVX = false;
        sf.texture.setFilters(Texture2D.Filter.NONE, Texture2D.Filter.NONE);

        return sf;
    }
}


